home *** CD-ROM | disk | FTP | other *** search
/ Languguage OS 2 / Languguage OS II Version 10-94 (Knowledge Media)(1994).ISO / gnu / gas_251.zip / bin_251 / opcodes / m88k-dis.c < prev    next >
C/C++ Source or Header  |  1993-09-29  |  9KB  |  329 lines

  1. /* Print instructions for the Motorola 88000, for GDB and GNU Binutils.
  2.    Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1993
  3.    Free Software Foundation, Inc.
  4.    Contributed by Data General Corporation, November 1989.
  5.    Partially derived from an earlier printcmd.c.
  6.  
  7. This file is part of GDB and the GNU Binutils.
  8.  
  9. This program is free software; you can redistribute it and/or modify
  10. it under the terms of the GNU General Public License as published by
  11. the Free Software Foundation; either version 2 of the License, or
  12. (at your option) any later version.
  13.  
  14. This program is distributed in the hope that it will be useful,
  15. but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17. GNU General Public License for more details.
  18.  
  19. You should have received a copy of the GNU General Public License
  20. along with this program; if not, write to the Free Software
  21. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
  22.  
  23. #include "dis-asm.h"
  24. #include "opcode/m88k.h"
  25.  
  26. INSTAB  *hashtable[HASHVAL] = {0};
  27.  
  28. static int
  29. m88kdis PARAMS ((bfd_vma, unsigned long, struct disassemble_info *));
  30.  
  31. static void
  32. printop PARAMS ((struct disassemble_info *, OPSPEC *,
  33.          unsigned long, bfd_vma, int));
  34.  
  35. static void
  36. init_disasm PARAMS ((void));
  37.  
  38. static void
  39. install PARAMS ((INSTAB *instptr));
  40.  
  41. /*
  42. *        Disassemble an M88000 Instruction
  43. *
  44. *
  45. *       This module decodes the instruction at memaddr.
  46. *
  47. *            Revision History
  48. *
  49. *       Revision 1.0    11/08/85        Creation date by Motorola
  50. *            05/11/89    R. Trawick adapted to GDB interface.
  51. *            07/12/93    Ian Lance Taylor updated to
  52. *                    binutils interface.
  53. */
  54.  
  55. int
  56. print_insn_m88k (memaddr, info)
  57.      bfd_vma memaddr;
  58.      struct disassemble_info *info;
  59. {
  60.   bfd_byte buffer[4];
  61.   int status;
  62.  
  63.   /* Instruction addresses may have low two bits set. Clear them.    */
  64.   memaddr &=~ (bfd_vma) 3;
  65.  
  66.   status = (*info->read_memory_func) (memaddr, buffer, 4, info);
  67.   if (status != 0)
  68.     {
  69.       (*info->memory_error_func) (status, memaddr, info);
  70.       return -1;
  71.     }
  72.  
  73.   return m88kdis (memaddr, bfd_getb32 (buffer), info);
  74. }
  75.  
  76. /*
  77.  * disassemble the instruction in 'instruction'.
  78.  * 'pc' should be the address of this instruction, it will
  79.  *   be used to print the target address if this is a relative jump or call
  80.  * the disassembled instruction is written to 'info'.
  81.  * The function returns the length of this instruction in bytes.
  82.  */
  83.  
  84. static int
  85. m88kdis (pc, instruction, info)
  86.      bfd_vma pc;
  87.      unsigned long instruction;
  88.      struct disassemble_info *info;
  89. {
  90.   static int ihashtab_initialized = 0;
  91.   unsigned int opcode;
  92.   INSTAB *entry_ptr;
  93.   int opmask;
  94.   unsigned int class;
  95.  
  96.   if (! ihashtab_initialized)
  97.     init_disasm ();
  98.  
  99.   /* create the appropriate mask to isolate the opcode */
  100.   opmask = DEFMASK;
  101.   class = instruction & DEFMASK;
  102.   if ((class >= SFU0) && (class <= SFU7))
  103.     {
  104.       if (instruction < SFU1)
  105.     opmask = CTRLMASK;
  106.       else
  107.     opmask = SFUMASK;
  108.     }
  109.   else if (class == RRR)
  110.     opmask = RRRMASK;
  111.   else if (class == RRI10)
  112.     opmask = RRI10MASK;
  113.  
  114.   /* isolate the opcode */
  115.   opcode = instruction & opmask;
  116.  
  117.   /* search the hash table with the isolated opcode */
  118.   for (entry_ptr = hashtable[opcode % HASHVAL];
  119.        (entry_ptr != NULL) && (entry_ptr->opcode != opcode);
  120.        entry_ptr = entry_ptr->next)
  121.     ;
  122.  
  123.   if (entry_ptr == NULL)
  124.     (*info->fprintf_func) (info->stream, "word\t%08x", instruction);
  125.   else
  126.     {
  127.       (*info->fprintf_func) (info->stream, "%s", entry_ptr->mnemonic);
  128.       printop (info, &(entry_ptr->op1), instruction, pc, 1);
  129.       printop (info, &(entry_ptr->op2), instruction, pc, 0);
  130.       printop (info, &(entry_ptr->op3), instruction, pc, 0);
  131.     }
  132.  
  133.   return 4;
  134. }
  135.  
  136. /*
  137. *                      Decode an Operand of an Instruction
  138. *
  139. *            Functional Description
  140. *
  141. *       This module formats and writes an operand of an instruction to info
  142. *       based on the operand specification.  When the first flag is set this
  143. *       is the first operand of an instruction.  Undefined operand types
  144. *       cause a <dis error> message.
  145. *
  146. *            Parameters
  147. *    disassemble_info    where the operand may be printed
  148. *       OPSPEC  *opptr          Pointer to an operand specification
  149. *       UINT    inst            Instruction from which operand is extracted
  150. *    UINT    pc        PC of instruction; used for pc-relative disp.
  151. *       int     first           Flag which if nonzero indicates the first
  152. *                               operand of an instruction
  153. *
  154. *            Output
  155. *
  156. *       The operand specified is extracted from the instruction and is
  157. *       written to buf in the format specified. The operand is preceded
  158. *       by a comma if it is not the first operand of an instruction and it
  159. *       is not a register indirect form.  Registers are preceded by 'r' and
  160. *       hex values by '0x'.
  161. *
  162. *            Revision History
  163. *
  164. *       Revision 1.0    11/08/85        Creation date
  165. */
  166.  
  167. static void
  168. printop (info, opptr, inst, pc, first)
  169.      struct disassemble_info *info;
  170.      OPSPEC *opptr;
  171.      unsigned long inst;
  172.      bfd_vma pc;
  173.      int first;
  174. {
  175.   int extracted_field;
  176.   char *cond_mask_sym;
  177.  
  178.   if (opptr->width == 0)
  179.     return;
  180.  
  181.   if (! first)
  182.     {
  183.       switch (opptr->type)
  184.     {
  185.     case REGSC:
  186.     case CONT:
  187.       break;
  188.     default:
  189.       (*info->fprintf_func) (info->stream, ",");
  190.       break;
  191.     }
  192.     }
  193.  
  194.   switch (opptr->type)
  195.     {
  196.     case CRREG:
  197.       (*info->fprintf_func) (info->stream, "cr%d",
  198.                  UEXT (inst, opptr->offset, opptr->width));
  199.       break;
  200.  
  201.     case FCRREG:
  202.       (*info->fprintf_func) (info->stream, "fcr%d",
  203.                  UEXT (inst, opptr->offset, opptr->width));
  204.       break;
  205.  
  206.     case REGSC:
  207.       (*info->fprintf_func) (info->stream, "[r%d]",
  208.                  UEXT (inst, opptr->offset, opptr->width));
  209.       break;
  210.  
  211.     case REG:
  212.       (*info->fprintf_func) (info->stream, "r%d",
  213.                  UEXT (inst, opptr->offset, opptr->width));
  214.       break;
  215.  
  216.     case XREG:
  217.       (*info->fprintf_func) (info->stream, "x%d",
  218.                  UEXT (inst, opptr->offset, opptr->width));
  219.       break;
  220.  
  221.     case HEX:
  222.       extracted_field = UEXT (inst, opptr->offset, opptr->width);
  223.       if (extracted_field == 0)
  224.     (*info->fprintf_func) (info->stream, "0");
  225.       else
  226.     (*info->fprintf_func) (info->stream, "0x%02x", extracted_field);
  227.       break;
  228.  
  229.     case DEC:
  230.       extracted_field = UEXT (inst, opptr->offset, opptr->width);
  231.       (*info->fprintf_func) (info->stream, "%d", extracted_field);
  232.       break;
  233.  
  234.     case CONDMASK:
  235.       extracted_field = UEXT (inst, opptr->offset, opptr->width);
  236.       switch (extracted_field & 0x0f)
  237.     {
  238.     case 0x1: cond_mask_sym = "gt0"; break;
  239.     case 0x2: cond_mask_sym = "eq0"; break;
  240.     case 0x3: cond_mask_sym = "ge0"; break;
  241.     case 0xc: cond_mask_sym = "lt0"; break;
  242.     case 0xd: cond_mask_sym = "ne0"; break;
  243.     case 0xe: cond_mask_sym = "le0"; break;
  244.     default: cond_mask_sym = NULL; break;
  245.     }
  246.       if (cond_mask_sym != NULL)
  247.     (*info->fprintf_func) (info->stream, "%s", cond_mask_sym);
  248.       else
  249.     (*info->fprintf_func) (info->stream, "%x", extracted_field);
  250.       break;
  251.             
  252.     case PCREL:
  253.       (*info->print_address_func)
  254.     (pc + (4 * (SEXT (inst, opptr->offset, opptr->width))),
  255.      info);
  256.       break;
  257.  
  258.     case CONT:
  259.       (*info->fprintf_func) (info->stream, "%d,r%d",
  260.                  UEXT (inst, opptr->offset, 5),
  261.                  UEXT (inst, (opptr->offset) + 5, 5));
  262.       break;
  263.  
  264.     case BF:
  265.       (*info->fprintf_func) (info->stream, "%d<%d>",
  266.                   UEXT (inst, (opptr->offset) + 5, 5),
  267.                   UEXT (inst, opptr->offset, 5));
  268.       break;
  269.  
  270.     default:
  271.       (*info->fprintf_func) (info->stream, "# <dis error: %08x>", inst);
  272.     }
  273. }
  274.  
  275. /*
  276. *                 Initialize the Disassembler Instruction Table
  277. *
  278. *       Initialize the hash table and instruction table for the disassembler.
  279. *       This should be called once before the first call to disasm().
  280. *
  281. *            Parameters
  282. *
  283. *            Output
  284. *
  285. *       If the debug option is selected, certain statistics about the hashing
  286. *       distribution are written to stdout.
  287. *
  288. *            Revision History
  289. *
  290. *       Revision 1.0    11/08/85        Creation date
  291. */
  292.  
  293. static void
  294. init_disasm ()
  295. {
  296.    int i, size;
  297.  
  298.    for (i = 0; i < HASHVAL; i++)
  299.      hashtable[i] = NULL;
  300.  
  301.    size = sizeof (instructions) / sizeof (INSTAB);
  302.    for (i = 0; i < size; i++)
  303.      install (&instructions[i]);
  304. }
  305.  
  306. /*
  307. *       Insert an instruction into the disassembler table by hashing the
  308. *       opcode and inserting it into the linked list for that hash value.
  309. *
  310. *            Parameters
  311. *
  312. *       INSTAB *instptr         Pointer to the entry in the instruction table
  313. *                               to be installed
  314. *
  315. *       Revision 1.0    11/08/85        Creation date
  316. *            05/11/89    R. TRAWICK ADAPTED FROM MOTOROLA
  317. */
  318.  
  319. static void
  320. install (instptr)
  321.      INSTAB *instptr;
  322. {
  323.   unsigned int i;
  324.  
  325.   i = (instptr->opcode) % HASHVAL;
  326.   instptr->next = hashtable[i];
  327.   hashtable[i] = instptr;
  328. }
  329.